Introduction
Bulk RNA sequencing data on 24 pre-treatment breast cancer tumours
performed by Wu et al. [1] was downloaded from
GEO with accession GSE176078,
and associated
publication.
geo_id <- "GSE176078"
This dataset was sequenced using Illumina NextSeq 500 (Homo sapiens),
submitted on Apr 15 2014.
Breast cancers are clinically stratified based on:
- expression of the estrogen receptor (ER),
- expression of the progesterone receptor (PR), and
- overexpression of HER2 (or amplification of HER2
gene ERBB2)
This results in the following three clinical
subtypes within this dataset:
- Luminal ie. ER+; (ER+, PR+/-)
- HER2+; (HER2+, ER+/-, PR+/-)
- Triple Negative ie. TNBC; (ER-, PR-,
HER2-)
Breast cancers are also stratified on bulk transcriptomic profiling
via PAM50 gene signatures [2] describing five
molecular subtypes: Luminal A, Luminal B,
HER2-enriched, Basal-like, and Normal-like.
The ~70-80% concordance between clinical and molecular subtypes
motivated this study to improve functional understanding of breast
cancer in a broader and more coherent sense.
For this study, the clinical subtype conditions classified are as
follows:
HER2+ ; (HER2+, ER-,
PR+/-)
HER2+/ER+ ; (HER2+, ER+,
PR+/-)
ER+ ; (HER2-, ER+,
PR+/-)
TNBC ; (HER2-, ER-,
PR-)
The distribution of clinical subtypes across the 24 samples is shown
in table 1.
Table 1: Clinical breast cancer subtype splits in our dataset
| |
Count |
Percent |
| HER2+ |
2 |
8.33 |
| HER2+/ER+ |
2 |
8.33 |
| TNBC |
8 |
33.33 |
| ER+ |
12 |
50.00 |
| Total |
24 |
100.00 |
This leads to 16.6666667% of samples containing HER2
expression, and 41.6666667% of samples containing ER
expression, with the overlaps of these representing 8.3333333% of all
samples; 50% of those with HER2, 14.2857143% of those with
ER.
The raw counts were cleaned, mapped to HUGO Gene Nomenclature Committee
(HGNC) Symbols, and normalized to produce final counts which will be
used for the duration of this report.
Of the original 58387 genes, we were able to map and
produce 28712 unversioned, unique genes, of which filtering
outliers (keeping genes present in a minimum of 12 samples)
resulted in 14800 genes remaining. This results in the
following plots.
The density plot shows the distribution of the cleaned, filtered, and
normalized counts per million across all samples (varying colours). It
displays a smooth curve as the result of our pre-processing.
Figure 1: Density of minimum 12 samples filtered
and normalized CPM counts for 24 samples across four clinical subtypes
of breast cancer tissue
Dispersion was calculated using edgeR to describe
deviation of variance from the mean. The Biological Coefficient of
Variation (BCV) is dispersion-squared, and represents the mean-variance
relationship among genes.
Figure 2: Biological Coefficient of Variation
(Dispersion squared) for 24 samples across four clinical subtypes of
breast cancer tissue gene-wise
The normalized counts initialized above are formatted as shown by the
subsection displayed in table 2.
Table 2: Format of Normalized counts dataset as described above
| |
CID3586 |
CID3921 |
CID3941 |
CID3948 |
CID3963 |
| WASH7P |
17.5790 |
1.0450 |
14.7274 |
0.0000 |
28.5314 |
| CICP27 |
1.9276 |
3.6553 |
2.2895 |
0.0000 |
2.1353 |
| MTND2P28 |
175.8840 |
174.5844 |
168.6025 |
354.9525 |
450.4684 |
| MTATP6P1 |
413.8903 |
589.8450 |
462.3509 |
1053.1526 |
404.6456 |
| FAM87B |
2.6751 |
1.9207 |
2.7736 |
1.5650 |
2.4742 |
| LINC01128 |
26.6312 |
35.3648 |
17.6844 |
20.9555 |
21.8894 |
Differential Gene
Expression
Given our normalized expression dataset contains only grouped
classification via clinical subtypes, these are the obvious choice for
factors. But, due to the nature of these classifiers, the names
themselves represent binary pairing of HER2 and
ER expression and absence (in a clinical setting). This
provides some flexibility for analyzing differential expression since we
really have two protein expressions, with their binary pairing as the
clinical subtype classification.
The Multi-Dimensional Scaling (MDS) plot was produced using
limma on the normalized data, and it shows the distance
between samples factored by the four distinct clinical subtypes.

In the given MDS plot, notice that blue and
red are opposites (+/- and -/+),
purple is the intermediary between blue and
red (+/+), whereas green
represents TNBC: double negative (-/-).
Although progesterone is a marker for breast cancer, its expression is
not quantifiably present within the dataset, and so is not included.
However, TNBC implies PR is not overly
expressed as well.
In terms of these colours in relation to each other, you can see some
clustering appearing, although nothing is confidently distinct.
Calculate p-values
for each gene.
I redefine the model to include the clinical subtypes of breast
cancer as factors, both as four separate classifiers, and the binary
pairing of over/under expression of HER2 and
ER.
# aggregate model design
model_design <- model.matrix(~ types_df$subtype)
# split model design (binary pairs)
splt_model_design <- model.matrix(~ types_df$her2 + types_df$er)
Given both design choices, I used edgeR’s
Quasi likelihood model to create quasi-likelihood fits.
# normalized counts grouped by clinical subtype
d <- DGEList(counts=norm_matrix,
group=types_df$subtype)
# estimate dispersion on subtype model design
d_ <- estimateDisp(d, model_design)
qlfit <- glmQLFit(d_, model_design)
# in parallel, estimate dispersion on binary pairing model design
d_splt <- estimateDisp(d, splt_model_design)
qlfit_splt <- glmQLFit(d_splt, splt_model_design)
Now, we can use glmQLFTest to calculate the differential
expression according to this model.
# fit subtype model design
qlf.subtypes <- glmQLFTest(qlfit)
# fit split model design
qlf.her2p <- glmQLFTest(qlfit_splt,
coef='types_df$erTRUE')
qlf.erp <- glmQLFTest(qlfit_splt,
coef='types_df$her2TRUE')
At this point, we analyze the calculated p-values and aggregate our
top hits for each model.
# top tags for aggregate model design
top_hits <- topTags(qlf.subtypes,
sort.by = "PValue",
n = nrow(normalized_counts))
# tog tags for split model design
top_her2p <- topTags(qlf.her2p,
sort.by = "PValue",
n = nrow(normalized_counts))
top_erp <- topTags(qlf.erp,
sort.by = "PValue",
n = nrow(normalized_counts))
How many genes were
significantly differentially expressed?
For our three model designs (one aggregate, and two binary splits),
the following number of genes were significantly differentially
expressed before correction.
Table 3: Number of P-Values that are significantly differentially expressed for the three different model designs
| |
Significantly Differentially Expressed Genes |
| Aggregate across subtypes |
1462 |
| HER2 expression |
1240 |
| ER expression |
779 |
What thresholds did
you use and why?
A threshold of 0.05 for p-values is very standard. It
implies that statistically we will only achieve this outcome
5% of the time assuming the null hypothesis is true (our
null hypothesis being that there is no differential expression between
the clinical subtypes in these genes).
Multiple hypothesis
testing
edgeR’s analysis provides a FDR value,
which implies Benjamini-Hochberg, however I wanted to independently
verify.
corrected_top_hits <- p.adjust(top_hits$table$PValue,
method = "BH",
n = nrow(normalized_counts))
length(which(corrected_top_hits < 0.05))
[1] 3
So, using this correction method, only 3 genes pass correction for
significant differential expression.
Which method did
you use? and why?
As described, the False Discovery Rates provided by our analysis
match my independent understanding of the
Benjamini-Hochberg method.
This method is very applicable to our use-case since it is less
stringent than Bonferroni when it comes to having a large number of
hypotheses. It is best practice to use Benjamini-Hochberg first to see
which of your genes pass correction, and if you need a more stringent
corrective method, you can consider using Bonferroni. However,
Bonferroni is said to be more useful when you are testing a smaller
number of hypotheses which is generally not the case for RNA sequencing
data.
How many genes
passed correction?
For our two model designs, the following number of genes passed
correction for each classifier.
Table 4: Number of P-Values that are significantly differentially expressed for the three different model designs
| |
Significantly Differentially Expressed Genes |
Significantly Differentially Expressed Genes after correction |
| Aggregate across subtypes |
1462 |
3 |
| HER2 expression |
1240 |
0 |
| ER expression |
779 |
11 |
There is clearly a large reduction in number of genes significantly
differentially expressed.
For the aggregate model of clinical subtypes, only 3
genes passed correction for false discovery. No genes
passed correction for HER2 expression association, whereas
11 genes passed correction for ER expression
association.
The genes and their associated values are shown in the tables
below.
Amount of
differentially expressed genes
MA Plot
An MA Plot demonstrates the log-fold change in contrast to the
log-concentration for our counts. I use edgeR’s MA plot
functionality.
Volcano Plot
The volcano plot provides another visual for the spread of our
differentially expressed genes and their significance, both before and
after correction.
The green points are those with significant p-values before
correction, with the red points being significant genes after
correction.
Visualizing top
hits
Heatmap
Aggregating our top hits across clinical subtypes into a heatmap, we
can see the expression visually as shown, along with a heatmap
annotation corresponding to each binary pairing represented by the
subtype classifier.
Specifically for ER overexpression or lack thereof, I
added an additional heatmap.
Do conditions
cluster together? Explain.
In figure 9, there is very visibly a cluster demonstrated between
heat intensity and ER overexpression or lack thereof with
the genes primarily in the top half being generally highly expressed in
lack of ER, and lowly expressed in overexpression of
ER. Similarly, the lower half of genes primarily follow the
opposite trend; lower expression on ER- and higher
expression on ER+.
In figure 10, it is more difficult to see the cluster patterns.
Sample 1 has very intense RNA expressions in the top half of genes, but
its matching HER2+/ER- subtype lacks this at all. This
implies the association goes in a broader scale than lack of
ER for these genes. Despite 11 genes being associated with
overexpression of ER, it does not appear to show a visible
cluster on the heatmap like the aggregate design in figure 9 does pretty
well.
Thresholded
Over-Representation Analysis
With our significantly up-regulated, and down-regulated gene-sets, we
will run a thresholded gene-set enrichment analysis.
We have 807 up-regulated genes, and 655 down-regulated genes for our
aggregate model design across all clinical subtypes.
I query our genesets using gProfiler’s
GOSt.
# up and down regulated thresholded genes
all <- gost_res(unique(c(upreg, downreg)))
# only up regulated thresholded genes
up <- gost_res(upreg)
# only down regulated thresholded genes
down <- gost_res(downreg)
Table 7: Head of thresholded up and down regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.018483 |
GO:0046032 |
ADP catabolic process |
| 0.018483 |
GO:0046031 |
ADP metabolic process |
| 0.018483 |
GO:0006096 |
glycolytic process |
| 0.018483 |
GO:0009057 |
macromolecule catabolic process |
| 0.018483 |
GO:0009137 |
purine nucleoside diphosphate catabolic process |
Table 8: Head of thresholded up-regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.0151737 |
GO:0022613 |
ribonucleoprotein complex biogenesis |
| 0.0151737 |
GO:0009179 |
purine ribonucleoside diphosphate metabolic process |
| 0.0151737 |
GO:0009181 |
purine ribonucleoside diphosphate catabolic process |
| 0.0151737 |
GO:0009056 |
catabolic process |
| 0.0151737 |
GO:0046032 |
ADP catabolic process |
Table 9: Head of thresholded down-regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.0666454 |
GO:0031000 |
response to caffeine |
| 0.0666454 |
GO:0071871 |
response to epinephrine |
| 0.0666454 |
GO:0071872 |
cellular response to epinephrine stimulus |
| 0.0666454 |
GO:0032989 |
cellular anatomical entity morphogenesis |
| 0.0666454 |
GO:0055006 |
cardiac cell development |
Which method did you
choose and why?
I chose to use g:Profiler with R since it was well
documented by Ruth Isserlin [3] and I had familiarity with it
through the journal entry.
g:Profiler provides an ORA
(over-representation analysis) method, and this is exactly the method I
want to perform on my un-thresholded and thresholded data.
Which annotation data
did you use and why?
I chose the following annotation sources to get the most
comprehensive results for our functional enrichment analysis relative to
biological processes and gene ontology:
GO:BP :
Gene Ontology: Biological Processes
REAC : Reactome
WP : WikiPathways
GO:CC :
Gene Ontology: Cellular Components
GO:MF :
Gene Ontology: Molecular Function
KEGG :
Kyoto Encyclopedia of Genes and Genomes
GO:BP, REAC, and WP were
recommended by Professor Isserlin, however I ran the ORA using these and
found nothing jumped out from the resulting plots. As such, I revisited
to expand the scope of annotation sources in hopes for a more
informative result.
What version of the
annotation are you using?
For g:Profiler version information, I used:
g:Profiler version:
e112_eg59_p19_25aa4782
biomaRt version: 112
For the annotation sources selected in my query, I used:
GO:BP version annotations: BioMart classes:
releases/2024-10-27
REAC version annotations: BioMart classes:
2025-2-3
WP version 20250110
GO:CC version annotations: BioMart classes:
releases/2024-10-27
GO:MF version annotations: BioMart classes:
releases/2024-10-27
KEGG version KEGG FTP Release
2024-01-22
How many gene-sets
were returned with what thresholds?
Table X: Gene-set sizes for different maximum thresholds
| |
Max 100 |
Max 250 |
Max 1000 |
Max 100000 |
| Up & Down |
991 |
1646 |
2160 |
2380 |
| Up |
558 |
1123 |
1610 |
1829 |
| Down |
126 |
324 |
570 |
643 |
Table X: Gene-set sizes for different maximum thresholds with minimum intersection of 10
| |
Max 100 |
Max 250 |
Max 1000 |
Max 100000 |
| Up & Down |
119 |
514 |
942 |
1132 |
| Up |
49 |
314 |
698 |
886 |
| Down |
6 |
49 |
152 |
193 |
After thresholding with maximum value of 100 and minimum intersection
of 10, we can see the terms remain similar.
Table X: Head of thresholded up and down-regulated genes from ORA
| |
term_id |
term_name |
p_value |
significant |
| 1 |
GO:0046032 |
ADP catabolic process |
0.018483 |
TRUE |
| 2 |
GO:0046031 |
ADP metabolic process |
0.018483 |
TRUE |
| 3 |
GO:0006096 |
glycolytic process |
0.018483 |
TRUE |
| 5 |
GO:0009137 |
purine nucleoside diphosphate catabolic process |
0.018483 |
TRUE |
| 6 |
GO:0019364 |
pyridine nucleotide catabolic process |
0.018483 |
TRUE |
Table X: Head of thresholded up-regulated genes from ORA
| |
term_id |
term_name |
p_value |
significant |
| 2 |
GO:0009179 |
purine ribonucleoside diphosphate metabolic process |
0.0151737 |
TRUE |
| 3 |
GO:0009181 |
purine ribonucleoside diphosphate catabolic process |
0.0151737 |
TRUE |
| 5 |
GO:0046032 |
ADP catabolic process |
0.0151737 |
TRUE |
| 7 |
GO:0046031 |
ADP metabolic process |
0.0151737 |
TRUE |
| 8 |
GO:0006096 |
glycolytic process |
0.0151737 |
TRUE |
Table X: Head of thresholded down-regulated genes from ORA
| |
term_id |
term_name |
p_value |
significant |
| 4 |
GO:0032989 |
cellular anatomical entity morphogenesis |
0.0666454 |
FALSE |
| 7 |
GO:0010927 |
cellular component assembly involved in morphogenesis |
0.0666454 |
FALSE |
| 48 |
GO:0035051 |
cardiocyte differentiation |
0.0676004 |
FALSE |
| 135 |
GO:0010469 |
regulation of signaling receptor activity |
0.0937527 |
FALSE |
| 4333 |
GO:0005796 |
Golgi lumen |
0.0532868 |
FALSE |
As such, we find that up-regulated genes have some significant
gene-sets after thresholding, whereas our down-regulated struggles to
maintain significant values.
Our combination table shows us overlap with the up-regulated genes,
further supporting the significance of our up-regulation skewed
results.
Comparing
up-regulated and down-regulated separate vs. together
The following figures demonstrate the over-representation analysis
plots for both up & down regulated, up-regulated, and down-regulated
genes respectively with only a couple of points manually
highlighted.
Figure 11: Over-representation analysis of Up
and Down regulated significantly differentially expressed genes
Figure 12: Over-representation analysis of
Up-regulated significantly differentially expressed genes
Figure 13: Over-representation analysis of
Down-regulated significantly differentially expressed genes
How do these
results compare?
Since the up-regulated gene results tend to exceed the down-regulated
gene results in terms of term significance, the combined plot appears to
more closely resemble the up-regulated plot.
In our case, ORA of up and down-regulated genes in combination did
not have a large effect on the results, but this is because the
up-regulated genes overshadow the down-regulated. If this were a
different case, we could see the difference between the up- and
down-regulated plots overshadowed and melted by the combination plot. As
such, it is important to look at both up- and down-regulated
separately.
Although, in terms of our results of this analysis, although some
terms are significant according to our arbitrary threshold, none of them
are strikingly so with maximum -log(adjusted p-values) only reaching up
to about 3 maximum, whereas plots seen with stronger functional
enrichment presence reach up much higher towards 10-16+.
Interpretation
Do the
over-representation results support conclusions or mechanisms discussed
in the original paper?
The original paper includes substantially more processing of this
data in addition to the single-cell RNA sequencing data they acquired in
tandem, so it is difficult to say whether this supports those results.
None of my significant differentially expressed genes appear throughout
the report whatsoever. The discussion and results section for the bulk
RNA-sequencing is very lacklustre compared to the rest of the analysis
and results found by spatial resolution of single-cell RNA sequencing.
The RNA sequencing heatmap appears possibly similar to mine, although
they used scaled mean interaction score and subtyped only for
ER and TNBC as opposed to all clinical
subtypes. I can understand this approach since the HER2
subtype presence was relatively small compared to the rest of the
samples.
Conclusively, there is not much functional enrichment apparently
distinguishing the classified clinical subtypes of breast cancer;
although if we had to look at the most significant term(s), our analysis
would draw our attention to cadherin binding, ie. GO:0045296,
of which is not present in the paper’s conclusions.
Can you find
evidence, ie. publications, to support some of the results that you see?
How does this evidence support your results?
Continuing with the most significant GO term from our
analysis–cadherin binding–there is substantial evidence that cadherins
are integral to mammary gland function, and misexpression of these leads
to increased motility and consequently greater likelihood of metastases
[4].
E-cadherin is one of the most widely expressed tumour suppressors in
breast cancer, however cadherin-binding on its own is rather vague and
difficult to draw conclusions from. We can conclude, however, that
cadherins are associated with breast cancer in multiple ways, and so
cadherin-binding may be a distinguishable functional enrichment between
clinical subtypes.
Interestingly, one of our three
significantly differentially expressed genes after correction across
clinical subtypes of breast cancer is ANXA8 which is
associated with breast cancer [5]. Rosetti et al. suggested
ANXA8 is significantly higher in ER- subtypes
as opposed to ER+ subtypes [6] which warrants further
analysis from our study since across our range of clinical subtypes, we
noticed ANXA8 was significantly differentially expressed.
So our results support the claim that ANXA8 is expressed
differentially across these subtypes of breast cancer (although
specifics are not provided in our analysis yet).
So ultimately, no evidence concretely supports my results, however
there is some associated evidence that suggests my results are not
completely incorrect.
Acknowledgments
This paper makes use of packages knitr [7],
BiocManager [8], GEOquery [9],
kableExtra [10], edgeR [11],
limma [12], ComplexHeatmap [13],
circlize [14], gprofiler2 [15],
GSA [16], & ggplot2 [17].
Bibliography
1. Wu SZ, Al-Eryani G, Roden DL, Junankar S, Harvey K, Andersson A, et
al. A single-cell and spatially resolved atlas of human breast cancers.
Nature genetics. 2021;53:1334–47.
2. Parker JS, Mullins M, Cheang MC, Leung S, Voduc D, Vickery T, et al.
Supervised risk predictor of breast cancer based on intrinsic subtypes.
Journal of clinical oncology. 2009;27:1160–7.
4. Derycke LD, Bracke ME. N-cadherin in the spotlight of cell-cell
adhesion, differentiation, embryogenesis, invasion and signalling.
International Journal of Developmental Biology. 2004;48:463–76.
6. Rossetti S, Bshara W, Reiners JA, Corlazzoli F, Miller A, Sacchi N.
Harnessing 3D models of mammary epithelial morphogenesis: An off the
beaten path approach to identify candidate biomarkers of early stage
breast cancer. Cancer letters. 2016;380:375–83.
7. Xie Y.
Dynamic documents with
R and knitr. 2nd edition. Boca Raton, Florida: Chapman;
Hall/CRC; 2015.
11. Chen Y, Lun AT, McCarthy DJ, Chen L, Baldoni P, Ritchie ME, et al.
edgeR: Empirical
analysis of digital gene expression data in r. 2025.
12. Ritchie ME, Phipson B, Wu D, Hu Y, Law CW, Shi W, et al.
limma powers differential expression analyses for
RNA-sequencing and microarray studies. Nucleic Acids
Research. 2015;43:e47.
13. Gu Z. Complex heatmap visualization. iMeta. 2022.
https://doi.org/10.1002/imt2.43.
14. Gu Z, Gu L, Eils R, Schlesner M, Brors B. Circlize implements and
enhances circular visualization in r. Bioinformatics. 2014;30:2811–2.
15. Kolberg L, Raudvere U, Kuzmin I, Vilo J, Peterson H. gprofiler2– an
r package for gene list functional enrichment analysis and namespace
conversion toolset g:profiler. F1000Research. 2020;9 (ELIXIR).
16. Efron B, Tibshirani R.
GSA: Gene set analysis.
2024.
17. Wickham H, Chang W, Henry L, Pedersen TL, Takahashi K, Wilke C, et
al.
ggplot2: Create elegant data
visualisations using the grammar of graphics. 2024.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAyIgpzdWJ0aXRsZTogIkRpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gYW5kIFByZWxpbWluYXJ5IE9SQSIKYXV0aG9yOiAiQW5uYWJlbGxhIEJyZWdhenppIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB0cnVlCmJpYmxpb2dyYXBoeTogYTJfcmVmZXJlbmNlcy5iaWIKY3NsOiBiaW9tZWQtY2VudHJhbC5jc2wKbGluay1jaXRhdGlvbnM6IHRydWUKLS0tCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpsaWJyYXJ5KGtuaXRyKQppZiAoIXJlcXVpcmUoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKQoKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgiR0VPcXVlcnkiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiR0VPcXVlcnkiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiR0VPcXVlcnkiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgia2FibGVFeHRyYSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJrYWJsZUV4dHJhIil9LCAKICAgICAgICAgZmluYWxseSA9IGxpYnJhcnkoImthYmxlRXh0cmEiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgiZWRnZVIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZWRnZVIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZWRnZVIiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgibGltbWEiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygibGltbWEiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgibGltbWEiKSkKaWYgKCFyZXF1aXJlKCJDb21wbGV4SGVhdG1hcCIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJDb21wbGV4SGVhdG1hcCIpCmlmICghcmVxdWlyZSgiY2lyY2xpemUiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2lyY2xpemUiKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJncHJvZmlsZXIyIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImdwcm9maWxlcjIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZ3Byb2ZpbGVyMiIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJHU0EiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiR1NBIil9LCAKICAgICAgICAgZmluYWxseSA9IGxpYnJhcnkoIkdTQSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJnZ3Bsb3QyIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZ2dwbG90MiIpKQoKb3B0aW9ucyhrbml0ci50YWJsZS5mb3JtYXQgPSAiaHRtbCIpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCkJ1bGsgUk5BIHNlcXVlbmNpbmcgZGF0YSBvbiAyNCBwcmUtdHJlYXRtZW50IGJyZWFzdCBjYW5jZXIgdHVtb3VycyBwZXJmb3JtZWQgYnkgV3UgZXQgYWwuIFtAd3UyMDIxc2luZ2xlXSB3YXMgZG93bmxvYWRlZCBmcm9tIGBHRU9gIHdpdGggYWNjZXNzaW9uIFtHU0UxNzYwNzhdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvZ2VvL3F1ZXJ5L2FjYy5jZ2k/YWNjPUdTRTE3NjA3OCksIGFuZCBbYXNzb2NpYXRlZCBwdWJsaWNhdGlvbl0oaHR0cHM6Ly9wbWMubmNiaS5ubG0ubmloLmdvdi9hcnRpY2xlcy9QTUM5MDQ0ODIzLykuCgpgYGB7cn0KZ2VvX2lkIDwtICJHU0UxNzYwNzgiCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZ3NlIDwtIGdldEdFTyhnZW9faWQsIEdTRU1hdHJpeD1GQUxTRSkKZ3BsIDwtIG5hbWVzKGdzZUBncGxzKQpncGxfaW5mbyA8LSBNZXRhKGdldEdFTyhncGwpKQpgYGAKClRoaXMgZGF0YXNldCB3YXMgc2VxdWVuY2VkIHVzaW5nIGByIGdwbF9pbmZvJHRpdGxlYCwgc3VibWl0dGVkIG9uIGByIGdwbF9pbmZvJHN1Ym1pc3Npb25fZGF0ZWAuCgpCcmVhc3QgY2FuY2VycyBhcmUgY2xpbmljYWxseSBzdHJhdGlmaWVkIGJhc2VkIG9uOgoKLSBleHByZXNzaW9uIG9mIHRoZSBlc3Ryb2dlbiByZWNlcHRvciAoKkVSKiksIAotIGV4cHJlc3Npb24gb2YgdGhlIHByb2dlc3Rlcm9uZSByZWNlcHRvciAoKlBSKiksIGFuZAotIG92ZXJleHByZXNzaW9uIG9mICpIRVIyKiAob3IgYW1wbGlmaWNhdGlvbiBvZiAqSEVSMiogZ2VuZSAqRVJCQjIqKQoKVGhpcyByZXN1bHRzIGluIHRoZSBmb2xsb3dpbmcgdGhyZWUgX19jbGluaWNhbCBzdWJ0eXBlc19fIHdpdGhpbiB0aGlzIGRhdGFzZXQ6CgotIEx1bWluYWwgaWUuIEVSKzsgKCpFUisqLCAqUFIrLy0qKQotIEhFUjIrOyAoKkhFUjIrKiwgKkVSKy8tKiwgKlBSKy8tKikKLSBUcmlwbGUgTmVnYXRpdmUgaWUuIFROQkM7ICgqRVItKiwgKlBSLSosICpIRVIyLSopCgpCcmVhc3QgY2FuY2VycyBhcmUgYWxzbyBzdHJhdGlmaWVkIG9uIGJ1bGsgdHJhbnNjcmlwdG9taWMgcHJvZmlsaW5nIHZpYSBQQU01MCBnZW5lIHNpZ25hdHVyZXMgW0BwYXJrZXIyMDA5c3VwZXJ2aXNlZF0gZGVzY3JpYmluZyBmaXZlIF9fbW9sZWN1bGFyIHN1YnR5cGVzX186IEx1bWluYWwgQSwgTHVtaW5hbCBCLCBIRVIyLWVucmljaGVkLCBCYXNhbC1saWtlLCBhbmQgTm9ybWFsLWxpa2UuCgpUaGUgfjcwLTgwJSBjb25jb3JkYW5jZSBiZXR3ZWVuIGNsaW5pY2FsIGFuZCBtb2xlY3VsYXIgc3VidHlwZXMgbW90aXZhdGVkIHRoaXMgc3R1ZHkgdG8gaW1wcm92ZSBmdW5jdGlvbmFsIHVuZGVyc3RhbmRpbmcgb2YgYnJlYXN0IGNhbmNlciBpbiBhIGJyb2FkZXIgYW5kIG1vcmUgY29oZXJlbnQgc2Vuc2UuCgpGb3IgdGhpcyBzdHVkeSwgdGhlIGNsaW5pY2FsIHN1YnR5cGUgY29uZGl0aW9ucyBjbGFzc2lmaWVkIGFyZSBhcyBmb2xsb3dzOgoKLSBgSEVSMitgIDsgKCpIRVIyKyosICpFUi0qLCAqUFIrLy0qKQotIGBIRVIyKy9FUitgIDsgKCpIRVIyKyosICpFUisqLCAqUFIrLy0qKQotIGBFUitgIDsgKCpIRVIyLSosICpFUisqLCAqUFIrLy0qKQotIGBUTkJDYCA7ICgqSEVSMi0qLCAqRVItKiwgKlBSLSopCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0Kbm9ybWFsaXplZF9jb3VudHMgPC0gcmVhZC50YWJsZSgKICBmaWxlPWZpbGUucGF0aChnZXR3ZCgpLCBnZW9faWQsCiAgICAgICAgICAgICAgICAgcGFzdGUoZ2VvX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAibm9ybWFsaXplZF9jb3VudHMudHh0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJfIikpLAogIGhlYWRlcj1UUlVFLCBzZXA9Ilx0IiwgCiAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwgCiAgY2hlY2submFtZXM9RkFMU0UpCmBgYAoKVGhlIGRpc3RyaWJ1dGlvbiBvZiBjbGluaWNhbCBzdWJ0eXBlcyBhY3Jvc3MgdGhlIDI0IHNhbXBsZXMgaXMgc2hvd24gaW4gdGFibGUgMS4KCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnR5cGVzIDwtIGRvLmNhbGwocmJpbmQsCiAgICAgICAgICAgICAgICAgbGFwcGx5KGdzZUBnc21zLCwKICAgICAgICAgICAgICAgICAgICAgICAgRlVOPWZ1bmN0aW9uKHgsIC4uLil7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYyh4QGhlYWRlciR0aXRsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhAaGVhZGVyJGNoYXJhY3RlcmlzdGljc19jaDEpfSkpWyxjKDEsMildCnR5cGVzWywyXSA8LSBnc3ViKHR5cGVzWywyXSwKICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJjbGluaWNhbF9zdWJ0eXBlOiAiLAogICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKQoKcHJlc2VudCA8LSBjb2xuYW1lcyhub3JtYWxpemVkX2NvdW50cykKdHlwZXMgPC0gdHlwZXNbd2hpY2godHlwZXNbLDFdICVpbiUgcHJlc2VudCksXQoKdHlwZXMgPC0gY2JpbmQodHlwZXMsIGdyZXBsKCJeW0hdW0VdW1JdWzJdWytdIiwgdHlwZXNbLDJdKSkKdHlwZXMgPC0gY2JpbmQodHlwZXMsIGdyZXBsKCJbRV1bUl1bK10kIiwgdHlwZXNbLDJdKSkKY29sbmFtZXModHlwZXMpIDwtIGMoInNhbXBsZSIsICJzdWJ0eXBlIiwgImhlcjIiLCAiZXIiKQp0eXBlc19kZiA8LSBhcy5kYXRhLmZyYW1lKHR5cGVzKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmhlcjIgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIkhFUjIrIikpCmhlcjJlciA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiSEVSMisvRVIrIikpCnRuYmMgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIlROQkMiKSkKZXIgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIkVSKyIpKQp0b3RhbCA9IHN1bShoZXIyLCBoZXIyZXIsIHRuYmMsIGVyKQoKc3VidHlwZV9jb3VudHMgPSBkYXRhLmZyYW1lKGMoaGVyMiwgaGVyMmVyLCB0bmJjLCBlciwgdG90YWwpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gYygiSEVSMisiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhFUjIrL0VSKyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVE5CQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRVIrIiwgIlRvdGFsIikpCnN1YnR5cGVfY291bnRzJHBlcmNlbnRhZ2VzID0gc3VidHlwZV9jb3VudHNbLDFdICogMTAwIC8gdG90YWwKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CnN1YnR5cGVfY291bnRzICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxOiBDbGluaWNhbCBicmVhc3QgY2FuY2VyIHN1YnR5cGUgc3BsaXRzIGluIG91ciBkYXRhc2V0IiwgCiAgICAgIGRpZ2l0cz0yLAogICAgICBjb2wubmFtZXM9YygiQ291bnQiLCAiUGVyY2VudCIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkgJT4lCiAgcm93X3NwZWMoNSwgYm9sZCA9IFQpCmBgYAoKVGhpcyBsZWFkcyB0byBgciA0MDAvMjRgJSBvZiBzYW1wbGVzIGNvbnRhaW5pbmcgYEhFUjJgIGV4cHJlc3Npb24sIGFuZCBgciAxMDAwLzI0YCUgb2Ygc2FtcGxlcyBjb250YWluaW5nIGBFUmAgZXhwcmVzc2lvbiwgd2l0aCB0aGUgb3ZlcmxhcHMgb2YgdGhlc2UgcmVwcmVzZW50aW5nIGByIDIwMC8yNGAlIG9mIGFsbCBzYW1wbGVzOyBgciAyMDAvNGAlIG9mIHRob3NlIHdpdGggYEhFUjJgLCBgciAyMDAvMTRgJSBvZiB0aG9zZSB3aXRoIGBFUmAuCgpUaGUgcmF3IGNvdW50cyB3ZXJlIGNsZWFuZWQsIG1hcHBlZCB0byBbSFVHTyBHZW5lIE5vbWVuY2xhdHVyZSBDb21taXR0ZWUgKEhHTkMpIFN5bWJvbHNdKGh0dHBzOi8vd3d3LmdlbmVuYW1lcy5vcmcvKSwgYW5kIG5vcm1hbGl6ZWQgdG8gcHJvZHVjZSBmaW5hbCBjb3VudHMgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciB0aGUgZHVyYXRpb24gb2YgdGhpcyByZXBvcnQuCgpPZiB0aGUgb3JpZ2luYWwgYDU4Mzg3YCBnZW5lcywgd2Ugd2VyZSBhYmxlIHRvIG1hcCBhbmQgcHJvZHVjZSBgMjg3MTJgIHVudmVyc2lvbmVkLCB1bmlxdWUgZ2VuZXMsIG9mIHdoaWNoIGZpbHRlcmluZyBvdXRsaWVycyAoa2VlcGluZyBnZW5lcyBwcmVzZW50IGluIGEgbWluaW11bSBvZiBgMTJgIHNhbXBsZXMpIHJlc3VsdGVkIGluIGAxNDgwMGAgZ2VuZXMgcmVtYWluaW5nLiBUaGlzIHJlc3VsdHMgaW4gdGhlIGZvbGxvd2luZyBwbG90cy4KClRoZSBkZW5zaXR5IHBsb3Qgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgY2xlYW5lZCwgZmlsdGVyZWQsIGFuZCBub3JtYWxpemVkIGNvdW50cyBwZXIgbWlsbGlvbiBhY3Jvc3MgYWxsIHNhbXBsZXMgKHZhcnlpbmcgY29sb3VycykuIEl0IGRpc3BsYXlzIGEgc21vb3RoIGN1cnZlIGFzIHRoZSByZXN1bHQgb2Ygb3VyIHByZS1wcm9jZXNzaW5nLgoKPGJyLz4KCiFbRmlndXJlIDE6IERlbnNpdHkgb2YgbWluaW11bSAxMiBzYW1wbGVzIGZpbHRlcmVkIGFuZCBub3JtYWxpemVkIENQTSBjb3VudHMgZm9yIDI0IHNhbXBsZXMgYWNyb3NzIGZvdXIgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciB0aXNzdWVdKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9HU0UxNzYwNzhfZmlsdF9ub3JtX2RlbnNpdHkucG5nKQoKPGJyLz4KRGlzcGVyc2lvbiB3YXMgY2FsY3VsYXRlZCB1c2luZyBgZWRnZVJgIHRvIGRlc2NyaWJlIGRldmlhdGlvbiBvZiB2YXJpYW5jZSBmcm9tIHRoZSBtZWFuLiBUaGUgQmlvbG9naWNhbCBDb2VmZmljaWVudCBvZiBWYXJpYXRpb24gKEJDVikgaXMgZGlzcGVyc2lvbi1zcXVhcmVkLCBhbmQgcmVwcmVzZW50cyB0aGUgbWVhbi12YXJpYW5jZSByZWxhdGlvbnNoaXAgYW1vbmcgZ2VuZXMuCgohW0ZpZ3VyZSAyOiBCaW9sb2dpY2FsIENvZWZmaWNpZW50IG9mIFZhcmlhdGlvbiAoRGlzcGVyc2lvbiBzcXVhcmVkKSBmb3IgMjQgc2FtcGxlcyBhY3Jvc3MgZm91ciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIHRpc3N1ZSBnZW5lLXdpc2VdKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9HU0UxNzYwNzhfYmN2LnBuZykKCjxici8+CgpUaGUgbm9ybWFsaXplZCBjb3VudHMgaW5pdGlhbGl6ZWQgYWJvdmUgYXJlIGZvcm1hdHRlZCBhcyBzaG93biBieSB0aGUgc3Vic2VjdGlvbiBkaXNwbGF5ZWQgaW4gdGFibGUgMi4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KaGVhZChub3JtYWxpemVkX2NvdW50c1sxOjVdKSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMjogRm9ybWF0IG9mIE5vcm1hbGl6ZWQgY291bnRzIGRhdGFzZXQgYXMgZGVzY3JpYmVkIGFib3ZlIiwgZGlnaXRzPTQpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMgRGlmZmVyZW50aWFsIEdlbmUgRXhwcmVzc2lvbgoKR2l2ZW4gb3VyIG5vcm1hbGl6ZWQgZXhwcmVzc2lvbiBkYXRhc2V0IGNvbnRhaW5zIG9ubHkgZ3JvdXBlZCBjbGFzc2lmaWNhdGlvbiB2aWEgY2xpbmljYWwgc3VidHlwZXMsIHRoZXNlIGFyZSB0aGUgb2J2aW91cyBjaG9pY2UgZm9yIGZhY3RvcnMuIEJ1dCwgZHVlIHRvIHRoZSBuYXR1cmUgb2YgdGhlc2UgY2xhc3NpZmllcnMsIHRoZSBuYW1lcyB0aGVtc2VsdmVzIHJlcHJlc2VudCBiaW5hcnkgcGFpcmluZyBvZiBgSEVSMmAgYW5kIGBFUmAgZXhwcmVzc2lvbiBhbmQgYWJzZW5jZSAoaW4gYSBjbGluaWNhbCBzZXR0aW5nKS4gVGhpcyBwcm92aWRlcyBzb21lIGZsZXhpYmlsaXR5IGZvciBhbmFseXppbmcgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gc2luY2Ugd2UgcmVhbGx5IGhhdmUgdHdvIHByb3RlaW4gZXhwcmVzc2lvbnMsIHdpdGggdGhlaXIgYmluYXJ5IHBhaXJpbmcgYXMgdGhlIGNsaW5pY2FsIHN1YnR5cGUgY2xhc3NpZmljYXRpb24uCgpUaGUgTXVsdGktRGltZW5zaW9uYWwgU2NhbGluZyAoTURTKSBwbG90IHdhcyBwcm9kdWNlZCB1c2luZyBgbGltbWFgIG9uIHRoZSBub3JtYWxpemVkIGRhdGEsIGFuZCBpdCBzaG93cyB0aGUgZGlzdGFuY2UgYmV0d2VlbiBzYW1wbGVzIGZhY3RvcmVkIGJ5IHRoZSBmb3VyIGRpc3RpbmN0IGNsaW5pY2FsIHN1YnR5cGVzLgo8YnIvPgoKYGBge3IgbWRzLXN1YnR5cGUsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLmNhcD0iRmlndXJlIDM6IE11bHRpLURpbWVuc2lvbmFsIFNjYWxpbmcgcGxvdCBmb3IgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciBhcyBjbGFzc2lmaWNhdGlvbnMgb2Ygb3ZlcmV4cHJlc3Npb24sIG9yIGxhY2sgdGhlcmVvZiwgb2YgRVIgYW5kIEhFUjIifQpub3JtX21hdHJpeCA8LSBhcy5tYXRyaXgobm9ybWFsaXplZF9jb3VudHMpCgpsaW1tYTo6cGxvdE1EUyhub3JtX21hdHJpeCwgbGFiZWxzPU5VTEwsIHBjaD0xLAogICAgICAgICAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICJwdXJwbGUiLCAiZ3JlZW4iKVtmYWN0b3IodHlwZXNfZGYkc3VidHlwZSldKQp0aXRsZSgiRmlndXJlIDM6IE1EUyBwbG90IG9mIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIiKQpsZWdlbmQoInRvcGxlZnQiLAogICAgICAgbGVnZW5kPWxldmVscyhmYWN0b3IodHlwZXNfZGYkc3VidHlwZSkpLAogICAgICAgcGNoPWMoMSksIGNvbD1jKCJibHVlIiwgInJlZCIsICJwdXJwbGUiLCAiZ3JlZW4iKSwKICAgICAgIHRpdGxlID0gIkNsaW5pY2FsIHN1YnR5cGUiLCBidHk9J24nLCBjZXg9MC43NSkKYGBgCgoKSW4gdGhlIGdpdmVuIE1EUyBwbG90LCBub3RpY2UgdGhhdCBgYmx1ZWAgYW5kIGByZWRgIGFyZSBvcHBvc2l0ZXMgKGArLy1gIGFuZCBgLS8rYCksIGBwdXJwbGVgIGlzIHRoZSBpbnRlcm1lZGlhcnkgYmV0d2VlbiBgYmx1ZWAgYW5kIGByZWRgIChgKy8rYCksIHdoZXJlYXMgYGdyZWVuYCByZXByZXNlbnRzIGBUTkJDYDogZG91YmxlIG5lZ2F0aXZlIChgLS8tYCkuIEFsdGhvdWdoIHByb2dlc3Rlcm9uZSBpcyBhIG1hcmtlciBmb3IgYnJlYXN0IGNhbmNlciwgaXRzIGV4cHJlc3Npb24gaXMgbm90IHF1YW50aWZpYWJseSBwcmVzZW50IHdpdGhpbiB0aGUgZGF0YXNldCwgYW5kIHNvIGlzIG5vdCBpbmNsdWRlZC4gSG93ZXZlciwgYFROQkNgIGltcGxpZXMgYFBSYCBpcyBub3Qgb3Zlcmx5IGV4cHJlc3NlZCBhcyB3ZWxsLgoKSW4gdGVybXMgb2YgdGhlc2UgY29sb3VycyBpbiByZWxhdGlvbiB0byBlYWNoIG90aGVyLCB5b3UgY2FuIHNlZSBzb21lIGNsdXN0ZXJpbmcgYXBwZWFyaW5nLCBhbHRob3VnaCBub3RoaW5nIGlzIGNvbmZpZGVudGx5IGRpc3RpbmN0LgoKIyMgQ2FsY3VsYXRlIHAtdmFsdWVzIGZvciBlYWNoIGdlbmUuIAoKSSByZWRlZmluZSB0aGUgbW9kZWwgdG8gaW5jbHVkZSB0aGUgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciBhcyBmYWN0b3JzLCBib3RoIGFzIGZvdXIgc2VwYXJhdGUgY2xhc3NpZmllcnMsIGFuZCB0aGUgYmluYXJ5IHBhaXJpbmcgb2Ygb3Zlci91bmRlciBleHByZXNzaW9uIG9mIGBIRVIyYCBhbmQgYEVSYC4KCmBgYHtyfQojIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24KbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHR5cGVzX2RmJHN1YnR5cGUpCgojIHNwbGl0IG1vZGVsIGRlc2lnbiAoYmluYXJ5IHBhaXJzKQpzcGx0X21vZGVsX2Rlc2lnbiA8LSBtb2RlbC5tYXRyaXgofiB0eXBlc19kZiRoZXIyICsgdHlwZXNfZGYkZXIpCmBgYAoKR2l2ZW4gYm90aCBkZXNpZ24gY2hvaWNlcywgSSB1c2VkIGBlZGdlUmAncyBgUXVhc2kgbGlrZWxpaG9vZCBtb2RlbGAgdG8gY3JlYXRlIHF1YXNpLWxpa2VsaWhvb2QgZml0cy4KCmBgYHtyfQojIG5vcm1hbGl6ZWQgY291bnRzIGdyb3VwZWQgYnkgY2xpbmljYWwgc3VidHlwZQpkIDwtIERHRUxpc3QoY291bnRzPW5vcm1fbWF0cml4LCAKICAgICAgICAgICAgIGdyb3VwPXR5cGVzX2RmJHN1YnR5cGUpCgojIGVzdGltYXRlIGRpc3BlcnNpb24gb24gc3VidHlwZSBtb2RlbCBkZXNpZ24KZF8gPC0gZXN0aW1hdGVEaXNwKGQsIG1vZGVsX2Rlc2lnbikKcWxmaXQgPC0gZ2xtUUxGaXQoZF8sIG1vZGVsX2Rlc2lnbikKCiMgaW4gcGFyYWxsZWwsIGVzdGltYXRlIGRpc3BlcnNpb24gb24gYmluYXJ5IHBhaXJpbmcgbW9kZWwgZGVzaWduCmRfc3BsdCA8LSBlc3RpbWF0ZURpc3AoZCwgc3BsdF9tb2RlbF9kZXNpZ24pCnFsZml0X3NwbHQgPC0gZ2xtUUxGaXQoZF9zcGx0LCBzcGx0X21vZGVsX2Rlc2lnbikKYGBgCgpOb3csIHdlIGNhbiB1c2UgYGdsbVFMRlRlc3RgIHRvIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYWNjb3JkaW5nIHRvIHRoaXMgbW9kZWwuCgpgYGB7cn0KIyBmaXQgc3VidHlwZSBtb2RlbCBkZXNpZ24KcWxmLnN1YnR5cGVzIDwtIGdsbVFMRlRlc3QocWxmaXQpCmBgYAoKYGBge3J9CiMgZml0IHNwbGl0IG1vZGVsIGRlc2lnbgpxbGYuaGVyMnAgPC0gZ2xtUUxGVGVzdChxbGZpdF9zcGx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0ndHlwZXNfZGYkZXJUUlVFJykKcWxmLmVycCA8LSBnbG1RTEZUZXN0KHFsZml0X3NwbHQsIAogICAgICAgICAgICAgICAgICAgICAgY29lZj0ndHlwZXNfZGYkaGVyMlRSVUUnKQpgYGAKCkF0IHRoaXMgcG9pbnQsIHdlIGFuYWx5emUgdGhlIGNhbGN1bGF0ZWQgcC12YWx1ZXMgYW5kIGFnZ3JlZ2F0ZSBvdXIgdG9wIGhpdHMgZm9yIGVhY2ggbW9kZWwuCgpgYGB7cn0KIyB0b3AgdGFncyBmb3IgYWdncmVnYXRlIG1vZGVsIGRlc2lnbgp0b3BfaGl0cyA8LSB0b3BUYWdzKHFsZi5zdWJ0eXBlcywgCiAgICAgICAgICAgICAgICAgICAgc29ydC5ieSA9ICJQVmFsdWUiLAogICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRzKSkKCiMgdG9nIHRhZ3MgZm9yIHNwbGl0IG1vZGVsIGRlc2lnbgp0b3BfaGVyMnAgPC0gdG9wVGFncyhxbGYuaGVyMnAsCiAgICAgICAgICAgICAgICAgICAgIHNvcnQuYnkgPSAiUFZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudHMpKQp0b3BfZXJwIDwtIHRvcFRhZ3MocWxmLmVycCwKICAgICAgICAgICAgICAgICAgIHNvcnQuYnkgPSAiUFZhbHVlIiwKICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRzKSkKYGBgCgojIyMgSG93IG1hbnkgZ2VuZXMgd2VyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZD8KCmBgYHtyLCBlY2hvPUZBTFNFfQojIGxlbmd0aCh3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KSkKIyBsZW5ndGgod2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKQojIGxlbmd0aCh3aGljaCh0b3BfcGVycCR0YWJsZSRQVmFsdWUgPCAwLjA1KSkKYGBgCgpGb3Igb3VyIHRocmVlIG1vZGVsIGRlc2lnbnMgKG9uZSBhZ2dyZWdhdGUsIGFuZCB0d28gYmluYXJ5IHNwbGl0cyksIHRoZSBmb2xsb3dpbmcgbnVtYmVyIG9mIGdlbmVzIHdlcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmVmb3JlIGNvcnJlY3Rpb24uCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iVGFibGUgMzogTnVtYmVyIG9mIFAtVmFsdWVzIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLCBpZS4gPCAwLjA1LCBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIn0KcHZhbHNfZGYgPC0gZGF0YS5mcmFtZSgKICBjKGxlbmd0aCh3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KSksCiAgICBsZW5ndGgod2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSksCiAgcm93Lm5hbWVzID0gYygiQWdncmVnYXRlIGFjcm9zcyBzdWJ0eXBlcyIsICJIRVIyIGV4cHJlc3Npb24iLCAiRVIgZXhwcmVzc2lvbiIpCikKCnB2YWxzX2RmICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAzOiBOdW1iZXIgb2YgUC1WYWx1ZXMgdGhhdCBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZm9yIHRoZSB0aHJlZSBkaWZmZXJlbnQgbW9kZWwgZGVzaWducyIsCiAgICAgICAgICAgICAgIGNvbC5uYW1lcz1jKCJTaWduaWZpY2FudGx5IERpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgojIyMgV2hhdCB0aHJlc2hvbGRzIGRpZCB5b3UgdXNlIGFuZCB3aHk/CgpBIHRocmVzaG9sZCBvZiBgMC4wNWAgZm9yIHAtdmFsdWVzIGlzIHZlcnkgc3RhbmRhcmQuIEl0IGltcGxpZXMgdGhhdCBzdGF0aXN0aWNhbGx5IHdlIHdpbGwgb25seSBhY2hpZXZlIHRoaXMgb3V0Y29tZSBgNWAlIG9mIHRoZSB0aW1lIGFzc3VtaW5nIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdHJ1ZSAob3VyIG51bGwgaHlwb3RoZXNpcyBiZWluZyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGJldHdlZW4gdGhlIGNsaW5pY2FsIHN1YnR5cGVzIGluIHRoZXNlIGdlbmVzKS4KCiMjIE11bHRpcGxlIGh5cG90aGVzaXMgdGVzdGluZwoKYGVkZ2VSYCdzIGFuYWx5c2lzIHByb3ZpZGVzIGEgYEZEUmAgdmFsdWUsIHdoaWNoIGltcGxpZXMgQmVuamFtaW5pLUhvY2hiZXJnLCBob3dldmVyIEkgd2FudGVkIHRvIGluZGVwZW5kZW50bHkgdmVyaWZ5LgoKYGBge3J9CmNvcnJlY3RlZF90b3BfaGl0cyA8LSBwLmFkanVzdCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50cykpCmxlbmd0aCh3aGljaChjb3JyZWN0ZWRfdG9wX2hpdHMgPCAwLjA1KSkKYGBgCgpTbywgdXNpbmcgdGhpcyBjb3JyZWN0aW9uIG1ldGhvZCwgb25seSAzIGdlbmVzIHBhc3MgY29ycmVjdGlvbiBmb3Igc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24uCgojIyMgV2hpY2ggbWV0aG9kIGRpZCB5b3UgdXNlPyBhbmQgd2h5PwoKQXMgZGVzY3JpYmVkLCB0aGUgRmFsc2UgRGlzY292ZXJ5IFJhdGVzIHByb3ZpZGVkIGJ5IG91ciBhbmFseXNpcyBtYXRjaCBteSBpbmRlcGVuZGVudCB1bmRlcnN0YW5kaW5nIG9mIHRoZSBfX0JlbmphbWluaS1Ib2NoYmVyZ19fIG1ldGhvZC4gCgpUaGlzIG1ldGhvZCBpcyB2ZXJ5IGFwcGxpY2FibGUgdG8gb3VyIHVzZS1jYXNlIHNpbmNlIGl0IGlzIGxlc3Mgc3RyaW5nZW50IHRoYW4gQm9uZmVycm9uaSB3aGVuIGl0IGNvbWVzIHRvIGhhdmluZyBhIGxhcmdlIG51bWJlciBvZiBoeXBvdGhlc2VzLiBJdCBpcyBiZXN0IHByYWN0aWNlIHRvIHVzZSBCZW5qYW1pbmktSG9jaGJlcmcgZmlyc3QgdG8gc2VlIHdoaWNoIG9mIHlvdXIgZ2VuZXMgcGFzcyBjb3JyZWN0aW9uLCBhbmQgaWYgeW91IG5lZWQgYSBtb3JlIHN0cmluZ2VudCBjb3JyZWN0aXZlIG1ldGhvZCwgeW91IGNhbiBjb25zaWRlciB1c2luZyBCb25mZXJyb25pLiBIb3dldmVyLCBCb25mZXJyb25pIGlzIHNhaWQgdG8gYmUgbW9yZSB1c2VmdWwgd2hlbiB5b3UgYXJlIHRlc3RpbmcgYSBzbWFsbGVyIG51bWJlciBvZiBoeXBvdGhlc2VzIHdoaWNoIGlzIGdlbmVyYWxseSBub3QgdGhlIGNhc2UgZm9yIFJOQSBzZXF1ZW5jaW5nIGRhdGEuCgojIyMgSG93IG1hbnkgZ2VuZXMgcGFzc2VkIGNvcnJlY3Rpb24/CgpGb3Igb3VyIHR3byBtb2RlbCBkZXNpZ25zLCB0aGUgZm9sbG93aW5nIG51bWJlciBvZiBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgZWFjaCBjbGFzc2lmaWVyLgoKYGBge3IsIGVjaG89RkFMU0V9CiMgbGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKQojIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkRkRSIDwgMC4wNSkpCiMgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkRkRSIDwgMC4wNSkpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5jYXA9IlRhYmxlIDQ6IE51bWJlciBvZiBQLVZhbHVlcyB0aGF0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCwgaWUuIDwgMC4wNSwgYmVmb3JlIGFuZCBhZnRlciBCZW5qYW1pbmktSG9jaGJlcmcgY29ycmVjdGlvbiBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIn0KcHZhbHNfZGYgPC0gZGF0YS5mcmFtZSgKICBjKGxlbmd0aCh3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KSksCiAgICBsZW5ndGgod2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSksCiAgcm93Lm5hbWVzID0gYygiQWdncmVnYXRlIGFjcm9zcyBzdWJ0eXBlcyIsICJIRVIyIGV4cHJlc3Npb24iLCAiRVIgZXhwcmVzc2lvbiIpCikKcHZhbHNfZGYgPC0gY2JpbmQocHZhbHNfZGYsIAogICAgICAgICAgICAgICAgICBjKGxlbmd0aCh3aGljaCh0b3BfaGl0cyR0YWJsZSRGRFIgPCAwLjA1KSksCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKHdoaWNoKHRvcF9oZXIycCR0YWJsZSRGRFIgPCAwLjA1KSksCiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkRkRSIDwgMC4wNSkpKSkKCnB2YWxzX2RmICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA0OiBOdW1iZXIgb2YgUC1WYWx1ZXMgdGhhdCBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZm9yIHRoZSB0aHJlZSBkaWZmZXJlbnQgbW9kZWwgZGVzaWducyIsCiAgICAgICAgICAgICAgIGNvbC5uYW1lcz1jKCJTaWduaWZpY2FudGx5IERpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU2lnbmlmaWNhbnRseSBEaWZmZXJlbnRpYWxseSBFeHByZXNzZWQgR2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpUaGVyZSBpcyBjbGVhcmx5IGEgbGFyZ2UgcmVkdWN0aW9uIGluIG51bWJlciBvZiBnZW5lcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZC4KCkZvciB0aGUgYWdncmVnYXRlIG1vZGVsIG9mIGNsaW5pY2FsIHN1YnR5cGVzLCBvbmx5IGAzYCBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgZmFsc2UgZGlzY292ZXJ5LiBfX05vX18gZ2VuZXMgcGFzc2VkIGNvcnJlY3Rpb24gZm9yIGBIRVIyYCBleHByZXNzaW9uIGFzc29jaWF0aW9uLCB3aGVyZWFzIGAxMWAgZ2VuZXMgcGFzc2VkIGNvcnJlY3Rpb24gZm9yIGBFUmAgZXhwcmVzc2lvbiBhc3NvY2lhdGlvbi4KClRoZSBnZW5lcyBhbmQgdGhlaXIgYXNzb2NpYXRlZCB2YWx1ZXMgYXJlIHNob3duIGluIHRoZSB0YWJsZXMgYmVsb3cuCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iVGFibGUgNTogR2VuZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMsIGFnZ3JlZ2F0ZSBkZXNpZ24ifQp0b3BfaGl0cyR0YWJsZVt0b3BfaGl0cyR0YWJsZSRGRFIgPCAwLjA1LF0KYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iVGFibGUgNjogR2VuZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYWZ0ZXIgY29ycmVjdGlvbiBhc3NvY2lhdGVkIHdpdGggRVIgb3ZlcmV4cHJlc3Npb24ifQp0b3BfZXJwJHRhYmxlW3RvcF9lcnAkdGFibGUkRkRSIDwgMC4wNSxdCmBgYAoKIyMgQW1vdW50IG9mIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcwoKIyMjIE1BIFBsb3QKCkFuIE1BIFBsb3QgZGVtb25zdHJhdGVzIHRoZSBsb2ctZm9sZCBjaGFuZ2UgaW4gY29udHJhc3QgdG8gdGhlIGxvZy1jb25jZW50cmF0aW9uIGZvciBvdXIgY291bnRzLiBJIHVzZSBgZWRnZVJgJ3MgTUEgcGxvdCBmdW5jdGlvbmFsaXR5LgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLmNhcD0iRmlndXJlIDQ6IE1BIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMsIGFnZ3JlZ2F0ZSBkZXNpZ24ifQplZGdlUjo6bWFQbG90KGxvZ0FidW5kYW5jZT10b3BfaGl0cyR0YWJsZSRsb2dDUE0sIAogICAgICAgICAgICAgIGxvZ0ZDPXRvcF9oaXRzJHRhYmxlJGxvZ0ZDLAogICAgICAgICAgICAgIGRlLnRhZ3M9d2hpY2godG9wX2hpdHMkdGFibGUkRkRSIDwgMC4wNSksCiAgICAgICAgICAgICAgbG93ZXNzPVRSVUUsCiAgICAgICAgICAgICAgeGxhYj0ibG9nKGNvdW50cyBwZXIgbWlsbGlvbikiLAogICAgICAgICAgICAgIHlsYWI9ImxvZyhmb2xkLWNoYW5nZSkiLAogICAgICAgICAgICAgIG1haW49IkZpZ3VyZSA0OiBNQSBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYWNyb3NzIAogICAgICAgICAgICAgIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIikKYGBgCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA1OiBNQSBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYXNzb2NpYXRlZCB3aXRoIEVSIGV4cHJlc3Npb24ifQplZGdlUjo6bWFQbG90KGxvZ0FidW5kYW5jZT10b3BfZXJwJHRhYmxlJGxvZ0NQTSwgCiAgICAgICAgICAgICAgbG9nRkM9dG9wX2VycCR0YWJsZSRsb2dGQywKICAgICAgICAgICAgICBkZS50YWdzPXdoaWNoKHRvcF9lcnAkdGFibGUkRkRSIDwgMC4wNSksCiAgICAgICAgICAgICAgbG93ZXNzPVRSVUUsCiAgICAgICAgICAgICAgeGxhYj0ibG9nKGNvdW50cyBwZXIgbWlsbGlvbikiLAogICAgICAgICAgICAgIHlsYWI9ImxvZyhmb2xkLWNoYW5nZSkiLAogICAgICAgICAgICAgIG1haW49IkZpZ3VyZSA1OiBNQSBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gCiAgICAgICAgICAgICAgYXNzb2NpYXRlZCB3aXRoIEVSIGV4cHJlc3Npb24iKQpgYGAKCiMjIyBWb2xjYW5vIFBsb3QKClRoZSB2b2xjYW5vIHBsb3QgcHJvdmlkZXMgYW5vdGhlciB2aXN1YWwgZm9yIHRoZSBzcHJlYWQgb2Ygb3VyIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbmQgdGhlaXIgc2lnbmlmaWNhbmNlLCBib3RoIGJlZm9yZSBhbmQgYWZ0ZXIgY29ycmVjdGlvbi4KClRoZSBncmVlbiBwb2ludHMgYXJlIHRob3NlIHdpdGggc2lnbmlmaWNhbnQgcC12YWx1ZXMgYmVmb3JlIGNvcnJlY3Rpb24sIHdpdGggdGhlIHJlZCBwb2ludHMgYmVpbmcgc2lnbmlmaWNhbnQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbi4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA2OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMsIGFnZ3JlZ2F0ZSBkZXNpZ24ifQpwbG90KHRvcF9oaXRzJHRhYmxlJGxvZ0ZDLCAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKSwKICAgICBtYWluPSJGaWd1cmUgNjogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gCiAgICAgYWNyb3NzIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGl0cyR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICBjb2w9ImdyZWVuIikKcG9pbnRzKHRvcF9oaXRzJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUpW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIGNvbD0icmVkIikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD02LCBmaWcuY2FwPSJGaWd1cmUgNzogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYXNzb2NpYXRlZCB3aXRoIEVSIGV4cHJlc3Npb24ifQpwbG90KHRvcF9lcnAkdGFibGUkbG9nRkMsIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSksCiAgICAgbWFpbj0iRmlndXJlIDc6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIAogICAgIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfZXJwJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgLTEwKmxvZzEwKHRvcF9lcnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIGNvbD0iZ3JlZW4iKQpwb2ludHModG9wX2VycCR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfZXJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSlbd2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KV0sCiAgICAgICBjb2w9InJlZCIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLmNhcD0iRmlndXJlIDg6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBIRVIyIGV4cHJlc3Npb24ifQpwbG90KHRvcF9oZXIycCR0YWJsZSRsb2dGQywgLTEwKmxvZzEwKHRvcF9oZXIycCR0YWJsZSRQVmFsdWUpLAogICAgIG1haW49IkZpZ3VyZSA4OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiAKICAgICBhc3NvY2lhdGVkIHdpdGggSEVSMiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgY29sPSJncmVlbiIpCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkRkRSIDwgMC4wNSldLAogICAgICAgY29sPSJyZWQiKQpgYGAKCiMjIFZpc3VhbGl6aW5nIHRvcCBoaXRzCgojIyMgSGVhdG1hcAoKQWdncmVnYXRpbmcgb3VyIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcyBpbnRvIGEgaGVhdG1hcCwgd2UgY2FuIHNlZSB0aGUgZXhwcmVzc2lvbiB2aXN1YWxseSBhcyBzaG93biwgYWxvbmcgd2l0aCBhIGhlYXRtYXAgYW5ub3RhdGlvbiBjb3JyZXNwb25kaW5nIHRvIGVhY2ggYmluYXJ5IHBhaXJpbmcgcmVwcmVzZW50ZWQgYnkgdGhlIHN1YnR5cGUgY2xhc3NpZmllci4KCmBgYHtyLCBlY2hvPUZBTFNFfQp0b3BzIDwtIHJvd25hbWVzKHFsZi5zdWJ0eXBlcyR0YWJsZSlbCiAgcWxmLnN1YnR5cGVzJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BfaGl0c19tYXRyaXggPSB0KHNjYWxlKAogIHQobm9ybV9tYXRyaXhbd2hpY2gocm93bmFtZXMobm9ybV9tYXRyaXgpICVpbiUgdG9wcyksXSkKKSkKCiMgY29sb3VycwppZiAobWluKHRvcF9oaXRzX21hdHJpeCkgPT0gMCkgewogIGhlYXRtYXBfY29sID0gY29sb3JSYW1wMihjKDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcF9oaXRzX21hdHJpeCksIDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKfQoKIyBhbm5vdGF0aW9ucwpoZXIyX2NvbCA8LSBjKCJsaWdodGdyZWVuIiwgInJlZCIpCm5hbWVzKGhlcjJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKZXJfY29sIDwtIGMoImRhcmtncmVlbiIsICJwaW5rIikKbmFtZXMoZXJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKCnR5cGVzX2RmJGhlcjIgPC0gZmFjdG9yKHR5cGVzX2RmJGhlcjIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQp0eXBlc19kZiRlciA8LSBmYWN0b3IodHlwZXNfZGYkZXIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQoKaGVhdG1hcF9hbm5vdGF0aW9uIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwQW5ub3RhdGlvbigKICBkZiA9IGRhdGEuZnJhbWUoaGVyMiA9IHR5cGVzX2RmJGhlcjIsCiAgICAgICAgICAgICAgICAgIGVyID0gdHlwZXNfZGYkZXIpLAogIGNvbCA9IGxpc3QoaGVyMiA9IGhlcjJfY29sLCBlciA9IGVyX2NvbCksCiAgc2hvd19sZWdlbmQ9VFJVRQopCgpoZWF0bWFwIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKGFzLm1hdHJpeCh0b3BfaGl0c19tYXRyaXgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X2RlbmQ9VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fZGVuZD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD1oZWF0bWFwX2NvbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fbmFtZXM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3dfbmFtZXM9RkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJjb2xvdXIgc2NhbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcF9hbm5vdGF0aW9uPWhlYXRtYXBfYW5ub3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5fdGl0bGU9IkZpZ3VyZSA5OiBIZWF0bWFwIG9mIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLmNhcD0iRmlndXJlIDk6IEhlYXQgbWFwIG9mIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiB3aXRoIGJpbmFyeSBsYWJlbGxpbmcifQpoZWF0bWFwCmBgYAoKU3BlY2lmaWNhbGx5IGZvciBgRVJgIG92ZXJleHByZXNzaW9uIG9yIGxhY2sgdGhlcmVvZiwgSSBhZGRlZCBhbiBhZGRpdGlvbmFsIGhlYXRtYXAuCgpgYGB7ciwgZWNobz1GQUxTRX0KdG9wc19lciA8LSByb3duYW1lcyhxbGYuZXJwJHRhYmxlKVsKICBxbGYuZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BzX2VyX21hdHJpeCA9IHQoc2NhbGUoCiAgdChub3JtX21hdHJpeFt3aGljaChyb3duYW1lcyhub3JtX21hdHJpeCkgJWluJSB0b3BzX2VyKSxdKQopKQoKIyBjb2xvdXJzCmlmIChtaW4odG9wc19lcl9tYXRyaXgpID09IDApIHsKICBoZWF0bWFwX2NvbCA9IGNvbG9yUmFtcDIoYygwLCBtYXgodG9wc19lcl9tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcHNfZXJfbWF0cml4KSwgMCwgbWF4KHRvcHNfZXJfbWF0cml4KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCn0KCmhlYXRtYXBfZXIgPC0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoYXMubWF0cml4KHRvcHNfZXJfbWF0cml4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd19kZW5kPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2w9aGVhdG1hcF9jb2wsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X25hbWVzPUZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iY29sb3VyIHNjYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfYW5ub3RhdGlvbj1oZWF0bWFwX2Fubm90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RpdGxlPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcuY2FwPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIn0KaGVhdG1hcF9lcgpgYGAKCiMjIyBEbyBjb25kaXRpb25zIGNsdXN0ZXIgdG9nZXRoZXI/IEV4cGxhaW4uCgpJbiBmaWd1cmUgOSwgdGhlcmUgaXMgdmVyeSB2aXNpYmx5IGEgY2x1c3RlciBkZW1vbnN0cmF0ZWQgYmV0d2VlbiBoZWF0IGludGVuc2l0eSBhbmQgYEVSYCBvdmVyZXhwcmVzc2lvbiBvciBsYWNrIHRoZXJlb2Ygd2l0aCB0aGUgZ2VuZXMgcHJpbWFyaWx5IGluIHRoZSB0b3AgaGFsZiBiZWluZyBnZW5lcmFsbHkgaGlnaGx5IGV4cHJlc3NlZCBpbiBsYWNrIG9mIGBFUmAsIGFuZCBsb3dseSBleHByZXNzZWQgaW4gb3ZlcmV4cHJlc3Npb24gb2YgYEVSYC4gU2ltaWxhcmx5LCB0aGUgbG93ZXIgaGFsZiBvZiBnZW5lcyBwcmltYXJpbHkgZm9sbG93IHRoZSBvcHBvc2l0ZSB0cmVuZDsgbG93ZXIgZXhwcmVzc2lvbiBvbiBgRVItYCBhbmQgaGlnaGVyIGV4cHJlc3Npb24gb24gYEVSK2AuCgpJbiBmaWd1cmUgMTAsIGl0IGlzIG1vcmUgZGlmZmljdWx0IHRvIHNlZSB0aGUgY2x1c3RlciBwYXR0ZXJucy4gU2FtcGxlIDEgaGFzIHZlcnkgaW50ZW5zZSBSTkEgZXhwcmVzc2lvbnMgaW4gdGhlIHRvcCBoYWxmIG9mIGdlbmVzLCBidXQgaXRzIG1hdGNoaW5nIGBIRVIyKy9FUi1gIHN1YnR5cGUgbGFja3MgdGhpcyBhdCBhbGwuIFRoaXMgaW1wbGllcyB0aGUgYXNzb2NpYXRpb24gZ29lcyBpbiBhIGJyb2FkZXIgc2NhbGUgdGhhbiBsYWNrIG9mIGBFUmAgZm9yIHRoZXNlIGdlbmVzLiBEZXNwaXRlIDExIGdlbmVzIGJlaW5nIGFzc29jaWF0ZWQgd2l0aCBvdmVyZXhwcmVzc2lvbiBvZiBgRVJgLCBpdCBkb2VzIG5vdCBhcHBlYXIgdG8gc2hvdyBhIHZpc2libGUgY2x1c3RlciBvbiB0aGUgaGVhdG1hcCBsaWtlIHRoZSBhZ2dyZWdhdGUgZGVzaWduIGluIGZpZ3VyZSA5IGRvZXMgcHJldHR5IHdlbGwuCgojIFRocmVzaG9sZGVkIE92ZXItUmVwcmVzZW50YXRpb24gQW5hbHlzaXMKCldpdGggb3VyIHNpZ25pZmljYW50bHkgdXAtcmVndWxhdGVkLCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZS1zZXRzLCB3ZSB3aWxsIHJ1biBhIHRocmVzaG9sZGVkIGdlbmUtc2V0IGVucmljaG1lbnQgYW5hbHlzaXMuCgpXZSBoYXZlIGByIGxlbmd0aCh3aGljaChxbGYuc3VidHlwZXMkdGFibGUkUFZhbHVlIDwgMC4wNSAmIHFsZi5zdWJ0eXBlcyR0YWJsZSRsb2dGQyA+IDApKWAgdXAtcmVndWxhdGVkIGdlbmVzLCBhbmQgYHIgbGVuZ3RoKHdoaWNoKHFsZi5zdWJ0eXBlcyR0YWJsZSRQVmFsdWUgPCAwLjA1ICYgcWxmLnN1YnR5cGVzJHRhYmxlJGxvZ0ZDIDwgMCkpYCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBmb3Igb3VyIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24gYWNyb3NzIGFsbCBjbGluaWNhbCBzdWJ0eXBlcy4KCmBgYHtyLCBlY2hvPUZBTFNFfQojIGNyZWF0ZSBub24tdGhyZXNob2xkZWQgZ2VuZSBzZXRzCm50X2dlbmVzZXQgPC0gcWxmLnN1YnR5cGVzJHRhYmxlCm50X2dlbmVzZXRbLCJyYW5rIl0gPC0gLWxvZzEwKG50X2dlbmVzZXQkUFZhbHVlKSAqCiAgc2lnbihudF9nZW5lc2V0JGxvZ0ZDKQpudF9nZW5lc2V0IDwtIG50X2dlbmVzZXRbb3JkZXIobnRfZ2VuZXNldCRyYW5rKSxdCgp3cml0ZS50YWJsZSh4PWRhdGEuZnJhbWUoZ2VuZV9uYW1lPXJvd25hbWVzKG50X2dlbmVzZXQpLAogICAgICAgICAgICAgICAgICAgICAgICAgRl9zdGF0PW50X2dlbmVzZXQkcmFuayksCiAgICAgICAgICAgIGZpbGU9ZmlsZS5wYXRoKGdldHdkKCksICJzdWJ0eXBlc19yYW5rZWRfZ2VuZWxpc3QudHh0IiksCiAgICAgICAgICAgIHNlcD0iXHQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgcXVvdGU9RkFMU0UpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CiMgY3JlYXRlIHRocmVzaG9sZGVkIGdlbmUgc2V0cwp1cHJlZyA8LSByb3duYW1lcyhudF9nZW5lc2V0KVt3aGljaChudF9nZW5lc2V0JFBWYWx1ZSA8IDAuMDUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJiBudF9nZW5lc2V0JGxvZ0ZDID4gMCldCmRvd25yZWcgPC0gcm93bmFtZXMobnRfZ2VuZXNldClbd2hpY2gobnRfZ2VuZXNldCRQVmFsdWUgPCAwLjA1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJiBudF9nZW5lc2V0JGxvZ0ZDIDwgMCldCgp3cml0ZS50YWJsZSh4PXVwcmVnLAogICAgICAgICAgICBmaWxlPWZpbGUucGF0aChnZXR3ZCgpLCAidXByZWdfZ2VuZXNfYWdncmVnYXRlLnR4dCIpLAogICAgICAgICAgICBzZXA9Ilx0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHF1b3RlPUZBTFNFKQp3cml0ZS50YWJsZSh4PWRvd25yZWcsCiAgICAgICAgICAgIGZpbGU9ZmlsZS5wYXRoKGdldHdkKCksICJkb3ducmVnX2dlbmVzX2FnZ3JlZ2F0ZS50eHQiKSwKICAgICAgICAgICAgc2VwPSJcdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBxdW90ZT1GQUxTRSkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KZ29zdF9yZXMgPC0gZnVuY3Rpb24ocXVlcnkpIHsKICByZXMgPC0gZ29zdChxdWVyeSA9IHF1ZXJ5LAogICAgICAgICAgICAgICAgICAgICAgc2lnbmlmaWNhbnQ9RkFMU0UsICMgc2V0IG91ciBvd24gdGhyZXNob2xkCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkX3F1ZXJ5ID0gVFJVRSwgIyBvcmRlcmVkIGJ5IHJhbmsKICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfaWVhPVRSVUUsICMgZXhjbHVkZSBlbGVjIEdPIGFubm90YXRpb25zCiAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLCAjIEJICiAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsCiAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBjKCJSRUFDIiwiV1AiLCJHTzpCUCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086Q0MiLCAiR086TUYiLCAiS0VHRyIpKQogIHJldHVybihyZXMpCn0KYGBgCgpJIHF1ZXJ5IG91ciBnZW5lc2V0cyB1c2luZyBgZ1Byb2ZpbGVyYCdzIGBHT1N0YC4KCmBgYHtyfQojIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwphbGwgPC0gZ29zdF9yZXModW5pcXVlKGModXByZWcsIGRvd25yZWcpKSkKIyBvbmx5IHVwIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwp1cCA8LSBnb3N0X3Jlcyh1cHJlZykKIyBvbmx5IGRvd24gcmVndWxhdGVkIHRocmVzaG9sZGVkIGdlbmVzCmRvd24gPC0gZ29zdF9yZXMoZG93bnJlZykKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KYWxsJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA3OiBIZWFkIG9mIHRocmVzaG9sZGVkIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcyBmcm9tIGc6R09TdCIpICU+JQogIGthYmxlX3N0eWxpbmcKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdXAkcmVzdWx0WzE6NSxjKDMsIDksIDExKV0gJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDg6IEhlYWQgb2YgdGhyZXNob2xkZWQgdXAtcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQpkb3duJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA5OiBIZWFkIG9mIHRocmVzaG9sZGVkIGRvd24tcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCiMjIFdoaWNoIG1ldGhvZCBkaWQgeW91IGNob29zZSBhbmQgd2h5PwoKSSBjaG9zZSB0byB1c2UgYGc6UHJvZmlsZXJgIHdpdGggUiBzaW5jZSBpdCB3YXMgd2VsbCBkb2N1bWVudGVkIGJ5IFJ1dGggSXNzZXJsaW4gW0ByaXNzZXJsaW5dIGFuZCBJIGhhZCBmYW1pbGlhcml0eSB3aXRoIGl0IHRocm91Z2ggdGhlIGpvdXJuYWwgZW50cnkuIAoKYGc6UHJvZmlsZXJgIHByb3ZpZGVzIGFuIGBPUkFgIChvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzKSBtZXRob2QsIGFuZCB0aGlzIGlzIGV4YWN0bHkgdGhlIG1ldGhvZCBJIHdhbnQgdG8gcGVyZm9ybSBvbiBteSB1bi10aHJlc2hvbGRlZCBhbmQgdGhyZXNob2xkZWQgZGF0YS4KCiMjIFdoaWNoIGFubm90YXRpb24gZGF0YSBkaWQgeW91IHVzZSBhbmQgd2h5PyAKCkkgY2hvc2UgdGhlIGZvbGxvd2luZyBhbm5vdGF0aW9uIHNvdXJjZXMgdG8gZ2V0IHRoZSBtb3N0IGNvbXByZWhlbnNpdmUgcmVzdWx0cyBmb3Igb3VyIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBhbmFseXNpcyByZWxhdGl2ZSB0byBiaW9sb2dpY2FsIHByb2Nlc3NlcyBhbmQgZ2VuZSBvbnRvbG9neToKCiogYEdPOkJQYCA6IGBHZW5lIE9udG9sb2d5OiBCaW9sb2dpY2FsIFByb2Nlc3Nlc2AKKiBgUkVBQ2AgOiBgUmVhY3RvbWVgCiogYFdQYCA6IGBXaWtpUGF0aHdheXNgCiogYEdPOkNDYCA6IGBHZW5lIE9udG9sb2d5OiBDZWxsdWxhciBDb21wb25lbnRzYAoqIGBHTzpNRmAgOiBgR2VuZSBPbnRvbG9neTogTW9sZWN1bGFyIEZ1bmN0aW9uYAoqIGBLRUdHYCA6IGBLeW90byBFbmN5Y2xvcGVkaWEgb2YgR2VuZXMgYW5kIEdlbm9tZXNgCgpgR086QlBgLCBgUkVBQ2AsIGFuZCBgV1BgIHdlcmUgcmVjb21tZW5kZWQgYnkgUHJvZmVzc29yIElzc2VybGluLCBob3dldmVyIEkgcmFuIHRoZSBPUkEgdXNpbmcgdGhlc2UgYW5kIGZvdW5kIG5vdGhpbmcganVtcGVkIG91dCBmcm9tIHRoZSByZXN1bHRpbmcgcGxvdHMuIEFzIHN1Y2gsIEkgcmV2aXNpdGVkIHRvIGV4cGFuZCB0aGUgc2NvcGUgb2YgYW5ub3RhdGlvbiBzb3VyY2VzIGluIGhvcGVzIGZvciBhIG1vcmUgaW5mb3JtYXRpdmUgcmVzdWx0LgoKIyMjIFdoYXQgdmVyc2lvbiBvZiB0aGUgYW5ub3RhdGlvbiBhcmUgeW91IHVzaW5nPwoKYGBge3IsIGVjaG89RkFMU0V9CnZlcnNpb25faW5mbyA8LSBncHJvZmlsZXIyOjpnZXRfdmVyc2lvbl9pbmZvKG9yZ2FuaXNtID0gImhzYXBpZW5zIikKZ29icCA8LSB2ZXJzaW9uX2luZm8kc291cmNlcyRgR086QlBgCmdvY2MgPC0gdmVyc2lvbl9pbmZvJHNvdXJjZXMkYEdPOkNDYApnb21mIDwtIHZlcnNpb25faW5mbyRzb3VyY2VzJGBHTzpNRmAKYGBgCgpGb3IgYGc6UHJvZmlsZXJgIHZlcnNpb24gaW5mb3JtYXRpb24sIEkgdXNlZDoKCiogYGc6UHJvZmlsZXJgIHZlcnNpb246IF9fYHIgdmVyc2lvbl9pbmZvJGdwcm9maWxlcl92ZXJzaW9uYF9fCiogYGJpb21hUnRgIHZlcnNpb246IF9fYHIgdmVyc2lvbl9pbmZvJGJpb21hcnRfdmVyc2lvbmBfXwoKRm9yIHRoZSBhbm5vdGF0aW9uIHNvdXJjZXMgc2VsZWN0ZWQgaW4gbXkgcXVlcnksIEkgdXNlZDoKCiogYEdPOkJQYCB2ZXJzaW9uIF9fYHIgZ29icCR2ZXJzaW9uYF9fIAoqIGBSRUFDYCB2ZXJzaW9uIF9fYHIgdmVyc2lvbl9pbmZvJHNvdXJjZXMkUkVBQyR2ZXJzaW9uYF9fCiogYFdQYCB2ZXJzaW9uIF9fYHIgdmVyc2lvbl9pbmZvJHNvdXJjZXMkV1AkdmVyc2lvbmBfXwoqIGBHTzpDQ2AgdmVyc2lvbiBfX2ByIGdvY2MkdmVyc2lvbmBfXyAKKiBgR086TUZgIHZlcnNpb24gX19gciBnb21mJHZlcnNpb25gX18gCiogYEtFR0dgIHZlcnNpb24gX19gciB2ZXJzaW9uX2luZm8kc291cmNlcyRLRUdHJHZlcnNpb25gX18KCiMjIEhvdyBtYW55IGdlbmUtc2V0cyB3ZXJlIHJldHVybmVkIHdpdGggd2hhdCB0aHJlc2hvbGRzPwoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQp0aHJlc2hvbGRfcmVzIDwtIGZ1bmN0aW9uKHJlc3VsdCwgbWluLCBtYXgsIGludGVyc2VjdGlvbikgewogIHJldCA8LSBzdWJzZXQocmVzdWx0LCB0ZXJtX3NpemUgPj0gbWluICYKICAgICAgICAgICAgICAgIHRlcm1fc2l6ZSA8PSBtYXggJgogICAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uX3NpemUgPj0gaW50ZXJzZWN0aW9uLAogICAgICAgICAgICAgICAgc2VsZWN0ID0gYyh0ZXJtX2lkLCB0ZXJtX25hbWUsIHBfdmFsdWUsIHNpZ25pZmljYW50KSkKICByZXR1cm4ocmV0KQp9CmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9kZiA8LSBkYXRhLmZyYW1lKAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMCwgNSkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDI1MCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAyNTAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAyNTAsIDUpKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAxMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAwLCA1KSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwMDAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMTAwMDAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAwMCwgNSkpWzFdKSwKICByb3cubmFtZXM9YygiVXAgJiBEb3duIiwgIlVwIiwgIkRvd24iKSkKCnRocmVzaG9sZF9kZiAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTA6IEdlbmUtc2V0IHNpemVzIGZvciBkaWZmZXJlbnQgbWF4aW11bSB0aHJlc2hvbGRzIHdpdGggbWluaW11bSBpbnRlcnNlY3Rpb24gb2YgNSIsCiAgICAgICAgICAgICAgIGNvbC5uYW1lcz1jKCJNYXggMTAwIiwgIk1heCAyNTAiLCAiTWF4IDEwMDAiLCAiTWF4IDEwMDAwMCIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdGhyZXNob2xkX2RmIDwtIGRhdGEuZnJhbWUoCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAxMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMCwgMTApKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAsIDEwKSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMjUwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAyNTAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMjUwLCAxMCkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMCwgMTApKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAxMDAwMCwgMTApKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMTAwMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMDAsIDEwKSlbMV0pLAogIHJvdy5uYW1lcz1jKCJVcCAmIERvd24iLCAiVXAiLCAiRG93biIpKQoKdGhyZXNob2xkX2RmICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxMTogR2VuZS1zZXQgc2l6ZXMgZm9yIGRpZmZlcmVudCBtYXhpbXVtIHRocmVzaG9sZHMgd2l0aCBtaW5pbXVtIGludGVyc2VjdGlvbiBvZiAxMCIsCiAgICAgICAgICAgICAgIGNvbC5uYW1lcz1jKCJNYXggMTAwIiwgIk1heCAyNTAiLCAiTWF4IDEwMDAiLCAiTWF4IDEwMDAwMCIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpBZnRlciB0aHJlc2hvbGRpbmcgd2l0aCBtYXhpbXVtIHZhbHVlIG9mIDEwMCBhbmQgbWluaW11bSBpbnRlcnNlY3Rpb24gb2YgMTAsIHdlIGNhbiBzZWUgdGhlIHRlcm1zIHJlbWFpbiBzaW1pbGFyLgoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwLCAxMClbMTo1LF0gJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDEyOiBIZWFkIG9mIHRocmVzaG9sZGVkIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBmcm9tIE9SQSIpICU+JQogIGthYmxlX3N0eWxpbmcKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMCwgMTApWzE6NSxdICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxMzogSGVhZCBvZiB0aHJlc2hvbGRlZCB1cC1yZWd1bGF0ZWQgZ2VuZXMgZnJvbSBPUkEiKSAlPiUKICBrYWJsZV9zdHlsaW5nCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMCwgMTApWzE6NSxdICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxNDogSGVhZCBvZiB0aHJlc2hvbGRlZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBmcm9tIE9SQSIpICU+JQogIGthYmxlX3N0eWxpbmcKYGBgCgpBcyBzdWNoLCB3ZSBmaW5kIHRoYXQgdXAtcmVndWxhdGVkIGdlbmVzIGhhdmUgc29tZSBzaWduaWZpY2FudCBnZW5lLXNldHMgYWZ0ZXIgdGhyZXNob2xkaW5nLCB3aGVyZWFzIG91ciBkb3duLXJlZ3VsYXRlZCBzdHJ1Z2dsZXMgdG8gbWFpbnRhaW4gc2lnbmlmaWNhbnQgdmFsdWVzLgoKT3VyIGNvbWJpbmF0aW9uIHRhYmxlIHNob3dzIHVzIG92ZXJsYXAgd2l0aCB0aGUgdXAtcmVndWxhdGVkIGdlbmVzLCBmdXJ0aGVyIHN1cHBvcnRpbmcgdGhlIHNpZ25pZmljYW5jZSBvZiBvdXIgdXAtcmVndWxhdGlvbiBza2V3ZWQgcmVzdWx0cy4KCiMjIENvbXBhcmluZyB1cC1yZWd1bGF0ZWQgYW5kIGRvd24tcmVndWxhdGVkIHNlcGFyYXRlIHZzLiB0b2dldGhlcgoKVGhlIGZvbGxvd2luZyBmaWd1cmVzIGRlbW9uc3RyYXRlIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHBsb3RzIGZvciBib3RoIHVwICYgZG93biByZWd1bGF0ZWQsIHVwLXJlZ3VsYXRlZCwgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzIHJlc3BlY3RpdmVseSB3aXRoIG9ubHkgYSBjb3VwbGUgb2YgcG9pbnRzIG1hbnVhbGx5IGhpZ2hsaWdodGVkLgoKIVtGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24gcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvYWxsX29yYS5wbmcpCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD03LCBmaWcuY2FwPSJGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBhbGxfcGxvdCA8LSBnb3N0cGxvdChhbGwsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIGFsbF9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChhbGxfcGxvdCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086MDE0MDUxMyIpICkgKwojICAgZ2d0aXRsZSgiRmlndXJlIDExOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIFVwIGFuZCBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAo8YnIvPgoKIVtGaWd1cmUgMTI6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAtcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvdXBfb3JhLnBuZykKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTcsIGZpZy5jYXA9IkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMifQojIHVwX3Bsb3QgPC0gZ29zdHBsb3QodXAsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIHVwX3B1YiA8LSBwdWJsaXNoX2dvc3RwbG90KHVwX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hsaWdodF90ZXJtcyA9IGMoIkdPOjAwNDUyOTYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMiKQpgYGAKPGJyLz4KCiFbRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvZG93bl9vcmEucG5nKQoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NywgZmlnLmNhcD0iRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBkb3duX3Bsb3QgPC0gZ29zdHBsb3QoZG93biwgY2FwcGVkID0gRkFMU0UsIGludGVyYWN0aXZlID0gRkFMU0UpCiMgZG93bl9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChkb3duX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMDMxOTgxIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAoKIyMjIEhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmU/CgpTaW5jZSB0aGUgdXAtcmVndWxhdGVkIGdlbmUgcmVzdWx0cyB0ZW5kIHRvIGV4Y2VlZCB0aGUgZG93bi1yZWd1bGF0ZWQgZ2VuZSByZXN1bHRzIGluIHRlcm1zIG9mIHRlcm0gc2lnbmlmaWNhbmNlLCB0aGUgY29tYmluZWQgcGxvdCBhcHBlYXJzIHRvIG1vcmUgY2xvc2VseSByZXNlbWJsZSB0aGUgdXAtcmVndWxhdGVkIHBsb3QuCgpJbiBvdXIgY2FzZSwgT1JBIG9mIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBpbiBjb21iaW5hdGlvbiBkaWQgbm90IGhhdmUgYSBsYXJnZSBlZmZlY3Qgb24gdGhlIHJlc3VsdHMsIGJ1dCB0aGlzIGlzIGJlY2F1c2UgdGhlIHVwLXJlZ3VsYXRlZCBnZW5lcyBvdmVyc2hhZG93IHRoZSBkb3duLXJlZ3VsYXRlZC4gSWYgdGhpcyB3ZXJlIGEgZGlmZmVyZW50IGNhc2UsIHdlIGNvdWxkIHNlZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB1cC0gYW5kIGRvd24tcmVndWxhdGVkIHBsb3RzIG92ZXJzaGFkb3dlZCBhbmQgbWVsdGVkIGJ5IHRoZSBjb21iaW5hdGlvbiBwbG90LiBBcyBzdWNoLCBpdCBpcyBpbXBvcnRhbnQgdG8gbG9vayBhdCBib3RoIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgc2VwYXJhdGVseS4KCkFsdGhvdWdoLCBpbiB0ZXJtcyBvZiBvdXIgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzLCBhbHRob3VnaCBzb21lIHRlcm1zIGFyZSBzaWduaWZpY2FudCBhY2NvcmRpbmcgdG8gb3VyIGFyYml0cmFyeSB0aHJlc2hvbGQsIG5vbmUgb2YgdGhlbSBhcmUgc3RyaWtpbmdseSBzbyB3aXRoIG1heGltdW0gLWxvZyhhZGp1c3RlZCBwLXZhbHVlcykgb25seSByZWFjaGluZyB1cCB0byBhYm91dCAzIG1heGltdW0sIHdoZXJlYXMgcGxvdHMgc2VlbiB3aXRoIHN0cm9uZ2VyIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBwcmVzZW5jZSByZWFjaCB1cCBtdWNoIGhpZ2hlciB0b3dhcmRzIDEwLTE2Ky4KCiMgSW50ZXJwcmV0YXRpb24KCiMjIERvIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc21zIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/CgpUaGUgb3JpZ2luYWwgcGFwZXIgaW5jbHVkZXMgc3Vic3RhbnRpYWxseSBtb3JlIHByb2Nlc3Npbmcgb2YgdGhpcyBkYXRhIGluIGFkZGl0aW9uIHRvIHRoZSBzaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyBkYXRhIHRoZXkgYWNxdWlyZWQgaW4gdGFuZGVtLCBzbyBpdCBpcyBkaWZmaWN1bHQgdG8gc2F5IHdoZXRoZXIgdGhpcyBzdXBwb3J0cyB0aG9zZSByZXN1bHRzLiBOb25lIG9mIG15IHNpZ25pZmljYW50IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhcHBlYXIgdGhyb3VnaG91dCB0aGUgcmVwb3J0IHdoYXRzb2V2ZXIuIFRoZSBkaXNjdXNzaW9uIGFuZCByZXN1bHRzIHNlY3Rpb24gZm9yIHRoZSBidWxrIFJOQS1zZXF1ZW5jaW5nIGlzIHZlcnkgbGFja2x1c3RyZSBjb21wYXJlZCB0byB0aGUgcmVzdCBvZiB0aGUgYW5hbHlzaXMgYW5kIHJlc3VsdHMgZm91bmQgYnkgc3BhdGlhbCByZXNvbHV0aW9uIG9mIHNpbmdsZS1jZWxsIFJOQSBzZXF1ZW5jaW5nLiBUaGUgUk5BIHNlcXVlbmNpbmcgaGVhdG1hcCBhcHBlYXJzIHBvc3NpYmx5IHNpbWlsYXIgdG8gbWluZSwgYWx0aG91Z2ggdGhleSB1c2VkIHNjYWxlZCBtZWFuIGludGVyYWN0aW9uIHNjb3JlIGFuZCBzdWJ0eXBlZCBvbmx5IGZvciBgRVJgIGFuZCBgVE5CQ2AgYXMgb3Bwb3NlZCB0byBhbGwgY2xpbmljYWwgc3VidHlwZXMuIEkgY2FuIHVuZGVyc3RhbmQgdGhpcyBhcHByb2FjaCBzaW5jZSB0aGUgYEhFUjJgIHN1YnR5cGUgcHJlc2VuY2Ugd2FzIHJlbGF0aXZlbHkgc21hbGwgY29tcGFyZWQgdG8gdGhlIHJlc3Qgb2YgdGhlIHNhbXBsZXMuCgpDb25jbHVzaXZlbHksIHRoZXJlIGlzIG5vdCBtdWNoIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBhcHBhcmVudGx5IGRpc3Rpbmd1aXNoaW5nIHRoZSBjbGFzc2lmaWVkIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXI7IGFsdGhvdWdoIGlmIHdlIGhhZCB0byBsb29rIGF0IHRoZSBtb3N0IHNpZ25pZmljYW50IHRlcm0ocyksIG91ciBhbmFseXNpcyB3b3VsZCBkcmF3IG91ciBhdHRlbnRpb24gdG8gY2FkaGVyaW4gYmluZGluZywgaWUuIFtHTzowMDQ1Mjk2XShodHRwczovL2FtaWdvLmdlbmVvbnRvbG9neS5vcmcvYW1pZ28vdGVybS9HTzowMDQ1Mjk2KSwgb2Ygd2hpY2ggaXMgbm90IHByZXNlbnQgaW4gdGhlIHBhcGVyJ3MgY29uY2x1c2lvbnMuCgojIyBDYW4geW91IGZpbmQgZXZpZGVuY2UsIGllLiBwdWJsaWNhdGlvbnMsIHRvIHN1cHBvcnQgc29tZSBvZiB0aGUgcmVzdWx0cyB0aGF0IHlvdSBzZWU/IEhvdyBkb2VzIHRoaXMgZXZpZGVuY2Ugc3VwcG9ydCB5b3VyIHJlc3VsdHM/CgpDb250aW51aW5nIHdpdGggdGhlIG1vc3Qgc2lnbmlmaWNhbnQgR08gdGVybSBmcm9tIG91ciBhbmFseXNpcy0tY2FkaGVyaW4gYmluZGluZy0tdGhlcmUgaXMgc3Vic3RhbnRpYWwgZXZpZGVuY2UgdGhhdCBjYWRoZXJpbnMgYXJlIGludGVncmFsIHRvIG1hbW1hcnkgZ2xhbmQgZnVuY3Rpb24sIGFuZCBtaXNleHByZXNzaW9uIG9mIHRoZXNlIGxlYWRzIHRvIGluY3JlYXNlZCBtb3RpbGl0eSBhbmQgY29uc2VxdWVudGx5IGdyZWF0ZXIgbGlrZWxpaG9vZCBvZiBtZXRhc3Rhc2VzIFtAZGVyeWNrZTIwMDRuXS4gRS1jYWRoZXJpbiBpcyBvbmUgb2YgdGhlIG1vc3Qgd2lkZWx5IGV4cHJlc3NlZCB0dW1vdXIgc3VwcHJlc3NvcnMgaW4gYnJlYXN0IGNhbmNlciwgaG93ZXZlciBjYWRoZXJpbi1iaW5kaW5nIG9uIGl0cyBvd24gaXMgcmF0aGVyIHZhZ3VlIGFuZCBkaWZmaWN1bHQgdG8gZHJhdyBjb25jbHVzaW9ucyBmcm9tLiBXZSBjYW4gY29uY2x1ZGUsIGhvd2V2ZXIsIHRoYXQgY2FkaGVyaW5zIGFyZSBhc3NvY2lhdGVkIHdpdGggYnJlYXN0IGNhbmNlciBpbiBtdWx0aXBsZSB3YXlzLCBhbmQgc28gY2FkaGVyaW4tYmluZGluZyBtYXkgYmUgYSBkaXN0aW5ndWlzaGFibGUgZnVuY3Rpb25hbCBlbnJpY2htZW50IGJldHdlZW4gY2xpbmljYWwgc3VidHlwZXMuCgpJbnRlcmVzdGluZ2x5LCBfX29uZV9fIG9mIG91ciBfX3RocmVlX18gc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciBpcyBgQU5YQThgIHdoaWNoIGlzIGFzc29jaWF0ZWQgd2l0aCBicmVhc3QgY2FuY2VyIFtAbWFsYV0uIFJvc2V0dGkgZXQgYWwuIHN1Z2dlc3RlZCBgQU5YQThgIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIGluIGBFUi1gIHN1YnR5cGVzIGFzIG9wcG9zZWQgdG8gYEVSK2Agc3VidHlwZXMgW0Byb3NzZXR0aTIwMTZoYXJuZXNzaW5nXSB3aGljaCB3YXJyYW50cyBmdXJ0aGVyIGFuYWx5c2lzIGZyb20gb3VyIHN0dWR5IHNpbmNlIGFjcm9zcyBvdXIgcmFuZ2Ugb2YgY2xpbmljYWwgc3VidHlwZXMsIHdlIG5vdGljZWQgYEFOWEE4YCB3YXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQuIFNvIG91ciByZXN1bHRzIHN1cHBvcnQgdGhlIGNsYWltIHRoYXQgYEFOWEE4YCBpcyBleHByZXNzZWQgZGlmZmVyZW50aWFsbHkgYWNyb3NzIHRoZXNlIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIgKGFsdGhvdWdoIHNwZWNpZmljcyBhcmUgbm90IHByb3ZpZGVkIGluIG91ciBhbmFseXNpcyB5ZXQpLgoKU28gdWx0aW1hdGVseSwgbm8gZXZpZGVuY2UgY29uY3JldGVseSBzdXBwb3J0cyBteSByZXN1bHRzLCBob3dldmVyIHRoZXJlIGlzIHNvbWUgYXNzb2NpYXRlZCBldmlkZW5jZSB0aGF0IHN1Z2dlc3RzIG15IHJlc3VsdHMgYXJlIG5vdCBjb21wbGV0ZWx5IGluY29ycmVjdC4KCiMgQWNrbm93bGVkZ21lbnRzCgpUaGlzIHBhcGVyIG1ha2VzIHVzZSBvZiBwYWNrYWdlcyBga25pdHJgIFtAa25pdHIyMDE1XSwgYEJpb2NNYW5hZ2VyYCBbQGJpb2NtYW5hZ2VyXSwgYEdFT3F1ZXJ5YCBbQFItR0VPcXVlcnldLCBga2FibGVFeHRyYWAgW0BrYWJsZWV4dHJhXSwgYGVkZ2VSYCBbQFItZWRnZVJdLCBgbGltbWFgIFtAbGltbWEyMDE1XSwgYENvbXBsZXhIZWF0bWFwYCBbQGNvbXBsZXhoZWF0bWFwXSwgYGNpcmNsaXplYCBbQGNpcmNsaXplXSwgYGdwcm9maWxlcjJgIFtAZ3Byb2ZpbGVyMl0sIGBHU0FgIFtAZ3NhXSwgJiBgZ2dwbG90MmAgW0BSLWdncGxvdDJdLgoKIyBCaWJsaW9ncmFwaHkK